/**
 * @file       SpamStat.cpp
 * @brief      
 * @author     韩玮
 * @version    1.0.0
 */

/*********************************************************************
 *  韩玮 2014年06月11日      Initial Version
 *********************************************************************/


#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <cstring>
#include <strings.h>
#include <string>
#include <map>
#include <vector>
#include <fstream>
#include <algorithm>
#include <queue>
#include	"hwutil.h"
using namespace std;
map<string, queue<string> > LogStore; 
bool cmp_i(const std::pair<const std::string,  int> &p1,  const std::pair<const std::string,  int> &p2)
{

	return p1.second > p2.second;//按second降序
} 
int imei_check(char* imei_src) 
{
	if(imei_src == NULL || strlen(imei_src) > 32 )
	{
		return 1; 
	}
	char imei_org[64] = {0} ; 
	char* p = imei_src ; 
	char* q = imei_org ; 
	while( *p == '0') p++ ; 
	int len = 0 ; 
	while( *p != '\0' and len < 32) 
	{
		*q++ = *p++ ; 
		len++;
	}
	*q = '\0'; 

	if(len < 14 || len > 15) 
		return 1 ; 
	int num[11]  =  {0} ; 
	for (int i = 0 ; i < len ;i++ ) {
		if(imei_org[i] >='0' && imei_org[i] <='9')
		{
			num[ imei_org[i] - '0'] ++ ; 
		}else
		{
			num[10]++; 
		}
	}
	if(num[10] > 0)
		return 2 ; 
	if(strstr(imei_org, "12345678") != NULL || strstr(imei_org, "23456789") != NULL ||
			strstr(imei_org, "87654321") != NULL || strstr(imei_org, "98765432") != NULL 
	  )
	{
		return 3; 
	}

	for ( int i=0; i<10;i++ ) {
		if(num[i] > 9 )
			return 4 ; 
	}

	return  0; 
}
string imei_int_to_string(int index)
{
	ostringstream os ; 
	os << index; 
	return os.str() ; 
}
void add_map(char* token[HW_MAX_TOKEN_NUM], int channel_num ,  int key_num ,   map<string, int> & m  )
{
	if( token[channel_num] != NULL && token[key_num] != NULL && *token[channel_num] != '\0' && *token[key_num] != '\0' )
	{
		string key ; 
		if( key_num == 0 &&  strlen(token[0]) == 19 )
		{
			char tmp[32] = {0} ; 
			memcpy(tmp, token[0]+11,2) ; 
			key = tmp ; 
		}else if( key_num == 6 || key_num == 13 || key_num == 14 || key_num == 16 || key_num == 3)
		{
			if(strncasecmp(token[key_num], "NULL", 4) == 0)
			{
				key = "NULL" ; 
			}else
			{
				key = token[key_num] ; 
			}

		}else if( key_num == 11 || key_num == 15)
		{
			if(strncasecmp( token[key_num] , "NULL", 4) == 0)
			{
				key = "NULL" ; 
			}else
			{
				key = "1" ;  
			} 
		}else if ( key_num == 17)
		{
			key = imei_int_to_string(imei_check( token[key_num])) ; 
		}

		map<string, int> :: iterator it ; 
		it = m.find(key) ; 

		if ( it != m.end() ) 
		{
			it->second++; 
		}else
		{
			m.insert(map<string, int>::value_type(key, 1)) ; 
		}

	}
}

int write_file_time(string key , int count ,  map<string, int > & m , ofstream & outfile, string suffix, int gc , int name)  
{

	outfile <<"--------------------------------------------------------------------------------" << endl; 
	if( m.size() == 0 )
	{
		outfile <<suffix<<"channel:"<<key<<"\tcount\t=\t"<<count << "\t[ERROR]"<<endl; 
		return -1 ; 
	}

	outfile <<suffix<<"channel:"<<key<<"\tcount = "<<count<<"\thour = "<< m.size()<< "\trate = "<< count*100.0/gc<<"%\t["<<name << "]"<<endl; 
	outfile << endl; 
	map<string, int>::iterator it ; 
	float global = 0; 
	char tmp[12] = {0} ; 
	for ( int i =0; i < 24;i++ ) {
		sprintf(tmp, "%02d", i) ; 
		it = m.find(tmp) ; 
		if( it != m.end())
		{
			global += it->second ; 
			outfile <<suffix<<"channel:"<<key<<"\t["<<it->first << "]\t"<<it->second<<"\t" << it->second*100.0/count <<"%\t" << global*100.0/ count <<"%"<< endl; 

		}else
		{
			outfile <<suffix<<"channel:"<<key<<"\t["<<tmp << "]\t"<<0<<"\t" << 0<<"%\t" << global*100.0/ count <<"%"<< endl; 

		}
	}

	outfile << endl; 
	return 0 ; 
}

int write_file_other(string key , int count ,   map<string, int >  & m , ofstream & outfile, string suffix, int gc, int name)  
{

	outfile <<"--------------------------------------------------"<< endl; 
	if( 0 == m.size())
	{
		outfile <<suffix<<"channel:"<<key<<"\tcount\t=\t"<<count << "\t[ERROR]"<<endl; 
		return -1 ; 
	}

	outfile <<suffix<<"channel:"<<key<<"\tcount:"<<count<<"\t"<<suffix<<":"<<m.size()<< "\trate:"<< count*100.0/gc<<"%\t["<<name <<"]"<<endl; 
	outfile << endl; 
	vector< pair< string,  int > > sortvector( m.begin(),  m.end() );
	sort(sortvector.begin(),  sortvector.end(),  cmp_i);
	vector< pair<string,  int> >::iterator it;
	int i = 0; 
	float global = 0; 
	bool flag = false; ; 
	int far = 20 ; 
	if(suffix == "ip")
		far = 40 ; 

	for ( it = sortvector.begin(); it != sortvector.end() && i<40; it++,i++) 
	{
		global += it->second ; 
		outfile<<setiosflags(ios::left)<<suffix<<"channel:"<<key<<"\t["<< setw(15)<<it->first << "]\t"<<setw(2)<<i<<"\t"<<setw(4)<<it->second<<"\t"<<setprecision(4) << it->second*100.0/count <<"%\t"<<setprecision(4) << global*100.0/ count <<"%"<< endl; 
		if(it->first == "NULL")
		{
			flag = true; 
		}
	}
	if( !flag && m["NULL"] > 0 )
	{ 
		outfile <<suffix<<"channel:"<<key<<"\t["<<"NULL"<< "]\t"<<m["NULL"]<<"\t" << m["NULL"]*100.0/count <<"%\t" << (global+m["NULL"])*100.0/ count <<"%"<< endl; 
	}
	outfile << endl; 

	return 0 ; 

}

bool log_cm_install ( string filename )
{
	//
	//	LOG_FILE << "----------------------------------------"  << endl ;
	FILE* fp = fopen(filename.c_str(), "r") ; 
	if(fp == NULL)
	{ 
		//		LOG_FILE	<< filename << "\t IS NOT EXIST  ,  please check it ..." << endl;
		return false; 
	}
	char buf[HW_MAX_BUF_NUM]  = {0}; 
	char* token[HW_MAX_TOKEN_NUM] ; 
	int num = 0 ; 
	struct hw_time ht; 
	string key ; 
	map<string, int> PvMap ; 

	int count = 0 ,fail_user = 0 ; 

	while ( fgets(buf, HW_MAX_BUF_NUM, fp) != NULL) {
		key = buf; 
		count++;
		num = hw_string_split(buf, token, '\t');
		if(hw_second_to_string_format_get(token[1], ht ) < 0 || ht.year < 2013 || ht.year > 2015 ) 
		{
			fail_user++; 
			continue; 
		}
		if(token[7] != NULL)
		{
			PvMap[ token[7]] ++ ; 
			LogStore[ token[7] ].push(key); 
		}
	}
	printf ( "%s\tcount = %d\tfail = %d \n", filename.c_str(), count, fail_user );
	fclose(fp) ; 
	fp = NULL; 
	string file_name = filename ; 
	std::size_t found ; 

	if ( (found = file_name.find_last_of("/")) != string::npos) {
		file_name = file_name.substr(found+1) ; 
	}
	file_name = "statip/" + file_name ; 

	vector< pair< string,  int > > sortvector( PvMap.begin(),  PvMap.end() );
	sort(sortvector.begin(),  sortvector.end(),  cmp_i);
	vector< pair<string,  int> >::iterator vit;

	string fn;
	fn = file_name + ".time"; 
	ofstream LOG_TIME (fn.c_str(), ios::out) ; 
	fn = file_name + ".other"; 
	ofstream LOG_OTHER (fn.c_str(), ios::out) ; 

	fn = file_name + ".ip"; 
	ofstream LOG_IP (fn.c_str(), ios::out) ; 
	int name = 0 ; 

	for(vit=sortvector.begin(); vit != sortvector.end() ; vit++)
	{
		map<string,queue<string> > :: iterator it = LogStore.find(vit->first) ; 
		if( it == LogStore.end() )
		{
			continue; 
		}
		queue<string> tmpQueue = it->second; 
		map<string, int> TimeMap; 
		map<string, int> VerMap ;  // 版本
		map<string, int> BrandMap ;//  NULL 占比 空
		map<string, int> ModelMap ;  //  NULL 占比 空

		map<string, int> MacMap;  // 有 没有 NULL 
		map<string, int> SerialMap;// 有 没有 NULL 
		map<string, int> RootMap;// 0 1 NULL 
		map<string, int> ImeiMap;// 0-4 
		map<string, int> IpMap;// 0-4 
		while( tmpQueue.size() > 0 )
		{
			key = tmpQueue.front(); 
			tmpQueue.pop(); 
			if( key.size() > HW_MAX_BUF_NUM)
			{
				continue; 
			}
			strcpy(buf,key.c_str()); 
			num = hw_string_split(buf, token, '\t');
			if(hw_second_to_string_format_get(token[1], ht ) < 0 || ht.year < 2013 || ht.year > 2015 ) 
			{
				fail_user++; 
				continue; 
			}
			add_map( token, 7,0,  TimeMap) ;  // 时区 
			add_map( token, 7,6,  VerMap) ;  // 全统计  Top 20 
			add_map( token, 7,11, MacMap) ;  // 不统计 
			add_map( token, 7,13, BrandMap) ;  //  全统计
			add_map( token, 7,14, ModelMap) ;  //  全统计
			add_map( token, 7,15, SerialMap) ;  // 不统计 
			add_map( token, 7,16, RootMap) ;  // 不统计 
			add_map( token, 7,17, ImeiMap) ;  // 不统计 
			add_map( token, 7,3, IpMap) ;  // 不统计 
		}
		name ++ ; 
		key = vit->first ; 
		write_file_time(key, vit->second, TimeMap, LOG_TIME , "tim", count, name) ; 
		LOG_OTHER << "************************************[\t"<< key << "\t]************************************"<< endl; 
		write_file_other(key, vit->second, VerMap, LOG_OTHER, "ver", count, name) ; 
		write_file_other(key, vit->second, MacMap, LOG_OTHER, "mac", count, name) ; 
		write_file_other(key, vit->second, SerialMap, LOG_OTHER, "ser", count, name) ; 
		write_file_other(key, vit->second, BrandMap, LOG_OTHER, "bra", count, name) ; 
		write_file_other(key, vit->second, ModelMap, LOG_OTHER, "mod", count, name) ; 
		write_file_other(key, vit->second, RootMap, LOG_OTHER, "roo", count, name) ; 
		write_file_other(key, vit->second, ImeiMap, LOG_OTHER, "imei", count, name) ; 
		write_file_other(key, vit->second, IpMap, LOG_IP, "ip", count, name) ; 
		#define MAP_CLEAR( DATAMAP) DATAMAP.clear(); 
		MAP_CLEAR(TimeMap);
		MAP_CLEAR(VerMap);MAP_CLEAR(MacMap);MAP_CLEAR(MacMap);MAP_CLEAR(SerialMap);
		MAP_CLEAR(BrandMap);MAP_CLEAR(BrandMap);MAP_CLEAR(ModelMap);
		MAP_CLEAR(RootMap);MAP_CLEAR(ImeiMap);MAP_CLEAR(IpMap);

	}

	return true; 
}

/**
 * @brief 
 */
int main ( int argc, char *argv[] )
{
	string str ; 
	str = argv[1] ; 
	log_cm_install(str) ; 
	return EXIT_SUCCESS;
}				// ----------  end of function main  ----------
